#include "stdafx.h"
#include "Phong.h"

Phong::Phong(){
	IAlambda = 0;
	ka = 0;
}

Phong::Phong(float IAlambda1, float ka1){
	IAlambda = IAlambda1;
	ka = ka1;

	if(IAlambda < 0)
		IAlambda = 0;
	if(IAlambda > 1)
		IAlambda = 1;
	if(ka < 0)
		ka = 0;
	if(ka > 1)
		ka = 1;
}

Phong::~Phong(){}

Phong::Phong(Phong const& ph){
	
}

Phong& Phong::operator=(Phong const& ph)
{
	return *this;
}

void Phong::setIAlambda(float Il){
	IAlambda = Il;
}
float Phong::getIAlambda(){
	return IAlambda;
}

void Phong::setKa(float k){
	ka = k;
}
float Phong::getKa(){
	return ka;
}

Couleur Phong::calculIllumination(std::vector<Source*> src, std::vector<Objet*> objets, Objet* obj, Observateur obs)
{
	Couleur c(0,0,0);

	Intersection inter = obj->getIntersection();
	Point pInter = inter.getPoint();

	if(obj->getTexture())
		c = obj->getCouleurTexture(pInter)*(ka*IAlambda);
	else
		c = obj->getCouleur()*(ka*IAlambda);	

	// calcul des ombres 			 
	//on parcourt toutes les sources de lumiere
	for (size_t j = 0; j < src.size(); ++j) {
		//vecteur de direction de la lumiere entre le point de la source et le point de l'intersection
		Vecteur lightDir(src.at(j)->getOrigineSource(),pInter);
		lightDir.normalize();
		//creation d'un rayon de lumiere
		Rayon lightRay(src.at(j)->getOrigineSource(), lightDir);

		Objet* obstacle = calculOmbre(lightRay, objets, obj);
		
		if(obstacle != NULL)
		{
			obj->setIntersection(inter);
			if(src.at(j)->getName().compare("Etendue")==0)
			{
				c+= calculIlluminationUneSource(src.at(j), obj, obs)*calculPenombre(src.at(j),objets,obj);
			}
			else
				c += calculIlluminationUneSource(src.at(j), obj, obs)*(obstacle->getProprietes().getCoffTrans());
		}
		else
		{
			obj->setIntersection(inter);
			c += calculIlluminationUneSource(src.at(j), obj, obs)*(1- obj->getProprietes().getCoffTrans());
		}
	}
	
	return c;
}

Couleur Phong::calculIlluminationUneSource(Source* src, Objet* obj, Observateur obs)
{
	Couleur c(0,0,0);
	//calcul des parametres de Phong

	Couleur couleurObjet;
	Point pInter = obj->getIntersection().getPoint();
	if(obj->getTexture())
		couleurObjet = obj->getCouleurTexture(pInter);
	else
		couleurObjet = obj->getCouleur();

	float kd = obj->getProprietes().getKd();

	Vecteur normale= obj->getIntersection().getNormale();
	float bump = obj->getProprietes().getBump();
	if(bump > 0.0f)
	{
		normale = obj->getProprietes().getNormale(obj->getIntersection());
	}

	normale.normalize();
	Vecteur vecteurLumiere(obj->getIntersection().getPoint(), src->getOrigineSource());
	vecteurLumiere.normalize();

	float NscalL = normale.produitScalaire(vecteurLumiere);

	float ks = obj->getProprietes().getKs();
	Vecteur vecteurV(obj->getIntersection().getPoint(),obs.getO_oeil());	
	vecteurV.normalize();
	Vecteur vecteurH = vecteurLumiere.addition(vecteurV);
	//Vecteur vecteurH = vecteurLumiere.median(vecteurV);
	vecteurH.normalize();

	float NscalH = normale.produitScalaire(vecteurH);
	
	float n = obj->getProprietes().getN();

	float distance = obj->getIntersection().getPoint().distance(src->getOrigineSource());
	float fatt = 1.0; //calculAttenuation(distance);

	Couleur speculaire = Couleur(1,1,1);

	//c = (src.getCouleur()*fatt)*(obj->getCouleur()*(kd*NscalL) + speculaire*ks*pow(NscalH, n));
	c = (couleurObjet*(kd*NscalL) + speculaire*ks*pow(NscalH, n));
	//c = obj->getCouleur()*(kd*NscalL);//+ ks*pow(NscalH, n);
	return c;
}

float Phong::calculPenombre(Source* source, std::vector<Objet*> objets, Objet* obj)
{
	Point sourcePoint = source->getOrigineSource();
	Point interPoint = obj->getIntersection().getPoint();
	Point sourcePointE(sourcePoint);
	Rayon ray;
	Vecteur lightDir;
	
	int num = 0;
	for(int i = 0; i < 25 ; i ++)
	{
		float t = 1.0f*(i+1)/25;
		sourcePointE.setX(sourcePoint.getX() -t);
		sourcePointE.setY(sourcePoint.getY() -t);
		sourcePointE.setZ(sourcePoint.getZ() -t);
		lightDir.setVecteur(sourcePointE, interPoint);
		ray.setDirection(lightDir);
		ray.setOrigine(sourcePointE);
		if(calculOmbre(ray, objets, obj) == NULL)
			num++;
		sourcePointE.setX(sourcePoint.getX() +t);
		sourcePointE.setY(sourcePoint.getY() +t);
		sourcePointE.setZ(sourcePoint.getZ() +t);
		lightDir.setVecteur(sourcePointE, interPoint);
		ray.setDirection(lightDir);
		ray.setOrigine(sourcePointE);
		if(calculOmbre(ray, objets, obj) == NULL)
			num++;
		
	}
	return 1.0f*num/50;
}

Objet* Phong::calculOmbre(Rayon lightRay, std::vector<Objet*> objets, Objet* obj)
{
	Objet* obstacle = NULL;

	obj->intersection(lightRay);
	float t = obj->getIntersection().getT();
	float t1 = 0.0f;

	//on parcourt tous les objets de la scene
	for (size_t i = 0; i < objets.size(); ++i) {
		//si il n'y a pas d'objet entre l'objet actuel et la source de lumiere alors on met ?jour la couleur	
		if (objets[i]->intersection(lightRay))
		{
			float tTemp = objets[i]->getIntersection().getT();
			if( tTemp < t && tTemp > t1) 
			{
				obstacle = objets[i];
				t1 = objets[i]->getIntersection().getT();
			}
		}	
	}

	return obstacle;
}